package com.xtaller.lazy.config.interceptor;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xtaller.lazy.lib.annotation.Permission;
import com.xtaller.lazy.lib.annotation.Token;
import com.xtaller.lazy.lib.bean.JWTResult;
import com.xtaller.lazy.lib.convert.J;
import com.xtaller.lazy.lib.convert.P;
import com.xtaller.lazy.lib.convert.S;
import com.xtaller.lazy.lib.convert.V;
import com.xtaller.lazy.lib.kit.InterceptorUtil;
import com.xtaller.lazy.lib.kit.JwtUtil;
import com.xtaller.lazy.model.base.User;
import com.xtaller.lazy.model.system.UserJwt;
import com.xtaller.lazy.service.base.UserService;
import com.xtaller.lazy.service.system.UserJwtService;
import com.xtaller.lazy.util.CacheUtil;
import io.jsonwebtoken.Claims;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-04-03
 * @Description: 基础拦截
 */
@Component
public class InterceptorBase implements HandlerInterceptor {
    @Autowired private CacheUtil cacheUtil;

    private P p = new P(this.getClass());
    private final String swaggerPath = "swagger-ui.html";
    private final String webJarPath = "/webjars/";

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws IOException {
        if (request.getRequestURL().indexOf(swaggerPath) >= 0) {
            return true;
        }
        if (request.getRequestURL().indexOf(webJarPath) >= 0) {
            return true;
        }
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        Token token = null;
        Permission permission = null;
        // 先做token拦截
        try {
            token = InterceptorUtil.getMethod(handler)
                    .getAnnotation(Token.class);

            permission = InterceptorUtil.getMethod(handler)
                    .getAnnotation(Permission.class);
        }catch (Exception ex){
            response.setStatus(404);
            response.getWriter().write(J.s2r("找不到对应路由"));
        }
        if (permission != null || token != null) {
            var access_token = request.getHeader("token");

            // 判断token是否为空
            if (V.isEmpty(access_token)) {
                response.setStatus(400);
                response.getWriter().write(J.s2r("token信息不能为空"));
                return false;
            }

            // 判断token有效性
            JWTResult jwt = JwtUtil.validateJWT(access_token);
            if (!jwt.isSuccess()) {
                response.setStatus(401);
                response.getWriter().write(J.s2r("非法Token信息"));
                return false;
            }

            // 判断token单点操作
            Claims claims = jwt.getClaims();
            var map = J.o2m(claims.getSubject());
            var key = S.apppend(map.get("platform"), "-", map.get("userId"));
            var uj = cacheUtil.getObject(key);
            if (uj == null) {
                cacheUtil.set(key, J.create());
                response.setStatus(401);
                response.getWriter().write(J.s2r("当前账户登录超时请重新登录"));
                return false;
            }
            if(!V.isEqual(uj.getString("jwt"), access_token)){
                cacheUtil.set(key, J.create());
                response.setStatus(401);
                response.getWriter().write(J.s2r("当前账户已在别处登录"));
                return false;
            }
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
